<?php
/**
 * File containing the BRail_User class.
 * @package BRail_User
 */

/**
 * @package BRail_User
 */
class BRail_User
{
    /**
     * Get Id number by MSNET login
     *
     * @param string $login
     * @return string
     * @throws Exception
     */
    public static function getIdentByLogin($login = null)
    {
        if (empty($login)) {
            throw new Exception('A login must be provided');
        }

        $login = strtoupper($login);

        switch (strlen($login)) {
                // External consultant - 3 letters followed 3 numbers
            case 6:
                $prefixEnd = array('T' => '00', 'A' => '01', 'B' => '02', 'C' => '03', 'D' => '04', 'E' => '05');
                if (! isset($prefixEnd[$login[2]])) {
                    throw new Exception('Invalid external login');
                }
                return '9999' . $prefixEnd[$login[2]] . substr($login, 3, 3);

                // Internal worker - 3 letters followed by 4 numbers
            case 7:
                $all = "ABCDEFGHIJKLMNOPQRSTUVWXY";
                $cons = "BCDFGHJKLMNPQRSTVWXZ";

                return self::getCompleteIdent(
                    // padding ident with 0's to reach 8 chars
                    sprintf(
                        "%04d%4s",
                        // 4 first numbers are the result of:
                        // the position in $all of the first letter * 400 +
                        // the position in $cons of the second letter * 20 +
                        // the position in $cons of the third letter
                        strpos($all, $login[0]) * 400 +
                        strpos($cons, $login[1]) * 20 +
                        strpos($cons, $login[2]),
                        substr($login, 3, 4)
                    )
                );

            default:
                if ($login == 'SYS_ WEBLDAP') {
                    return '99990000';
                } else {
                    throw new Exception('A login must contain 6 or 7 letters');
                }
        }
    }

    /**
     * Get MSNET login by Id number
     *
     * @param string $ident
     * @return string
     * @throws Exception
     */
    public static function getLoginByIdent($ident)
    {
        if (empty($ident) || ! ctype_digit($ident) || strlen($ident) != 9) {
            throw new Exception('An identification number composed of 9 DIGITS must be provided');
        }

        $all = "ABCDEFGHIJKLMNOPQRSTUVWXY";
        $cons = "BCDFGHJKLMNPQRSTVWXZ";

        if (substr($ident, 0, 4) !== '9999') {
            if (!self::checkIdent($ident)) {
                throw new Exception('Provided identification number is invalid');
            }
            // Take 4 chars starting at 5th position
            $secondPart = substr($ident, 4, 4);
            // Take 4 chars starting at 0 position
            $firstPart = substr($ident, 0, 4);
            // rest of a division by 20
            $rest = $firstPart - (floor($firstPart / 20) * 20);
            // floor of integer result of the division by 20
            $firstPart = floor($firstPart / 20);
            // take one char in string $alphShort at pos $rest
            $firstChar = $cons[$rest];
            $rest = $firstPart - (floor($firstPart / 20) * 20);
            $firstPart = floor($firstPart / 20);
            $secondChar = $cons[$rest];
            $rest = $firstPart - (floor($firstPart / 25) * 25);
            return $all[$rest] . $secondChar . $firstChar . $secondPart;
        }
        $loginPrefix = array('EXT', 'EXA', 'EXB', 'EXC', 'EXD', 'EXE');
        if (!isset($loginPrefix[$ident[5]])) {
            throw new Exception('Invalid external id');
        }
        return $loginPrefix[$ident[5]] . substr($ident, 6, 3);
    }

    /**
     * Calculate the 9th cipher of the Id number when provided the first 8 numbers
     * Function returns the complete ID (9 numbers)
     * @param string $ident
     * @return string
     * @throws Exception
     */
    public static function getCompleteIdent($ident)
    {
        if (empty($ident) || strlen($ident) !== 8 || !ctype_digit($ident)) {
            throw new Exception('An identification number composed of 8 DIGITS must be provided');
        }
        if (substr($ident, 0, 4) === '9999') {
            throw new Exception('Cannot calculate the last digit of an external user id');
        }

        $even = $ident[0] + $ident[2] + $ident[4] + $ident[6];
        $odd = $ident[1] . $ident[3] . $ident[5] . $ident[7];
        $strlenOdd = strlen($odd);

        $valArray = array(
            1 => 2,
            2 => 4,
            3 => 6,
            4 => 8,
            5 => 1,
            6 => 3,
            7 => 5,
            8 => 7
        );

        for ($i = 0; $i < $strlenOdd; $i++) {
            if (isset($valArray[$odd[$i]])) {
                $odd[$i] = $valArray[$odd[$i]];
            }
        }
        $odd = (int) $odd[0] + (int) $odd[1] + (int) $odd[2] + (int) $odd[3];

        $ccStr = (string) (100 - ($even + $odd));
        return $ident . $ccStr[1];
    }

    /**
     * Check if the given identification number is correct
     * If correct, return true
     * If not correct, return false
     * @param string $ident
     * @return boolean
     */
    public static function checkIdent($ident)
    {
        if (!(isset($ident) && strlen($ident) === 9)) {
            throw new Exception('An identification number composed of 9 DIGITS must be provided');
        }

        return self::getCompleteIdent(substr($ident, 0, 8)) == $ident;
    }
}
